﻿// -------------------------------------------------------------------------
//    @FileName         :    NFTransAccCreateRole.cpp
//    @Author           :    gaoyi
//    @Date             :    24-8-21
//    @Email            :    445267987@qq.com
//    @Module           :    NFTransAccCreateRole
//
// -------------------------------------------------------------------------

#include "NFTransAccCreateRole.h"
#include <NFComm/NFPluginModule/NFIKernelModule.h>
#include <NFServerComm/NFServerCommon/NFIServerMessageModule.h>

#include <DescStore/ActorDesc.h>
#include <DescStore/TransferDesc.h>

#include "ConstantDescEx.h"
#include "NFTransInsertName.h"
#include "NFTransLoadAcc.h"
#include "NFTransSaveAcc.h"
#include "NFTransInsertAcc.h"
#include "proto_svr_common.nanopb.h"
#include "NFComm/NFCore/NFServerTime.h"
#include "NFComm/NFCore/NFTimeUtility.h"
#include "NFLogicCommon/NFBaseDefine.h"
#include "OnlineAcc/NFOnlineAcc.h"
#include "OnlineAcc/NFOnlineAccMgr.h"

NFTransAccCreateRole::NFTransAccCreateRole()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFTransAccCreateRole::~NFTransAccCreateRole()
{
}

int NFTransAccCreateRole::CreateInit()
{
    m_iServerType = NF_ST_ONLINE_SERVER;
    m_ullRoleID = 0;
    m_fromBusId = 0;
    m_transId = 0;
    m_zoneId = 0;
    m_playerUin = 0;
    m_platformType = 0;
    SetState(EN_TCRS_INIT);
    return 0;
}

int NFTransAccCreateRole::ResumeInit()
{
    return 0;
}

int NFTransAccCreateRole::Init(int zoneId, uint64_t playerUin, int platformType, int fromBusId, int transId, const proto_ff::Proto_Zone2OnLineCreateRoleReq& oCreateRoleReq)
{
    m_zoneId = zoneId;
    m_playerUin = playerUin;
    m_ullRoleID = playerUin;
    m_platformType = platformType;
    m_fromBusId = fromBusId;
    m_transId = transId;

    InitData(oCreateRoleReq);
    return 0;
}

int NFTransAccCreateRole::StartInsertName()
{
    CHECK_EXPR(GetState() == EN_TCRS_INIT, proto_ff::ERR_CODE_SYSTEM_OBJSTATUS_INVALID, "invalid tran state! {}", DebugString());

    auto pActorDesc = ActorDesc::Instance()->GetDesc(m_stCreateRoleReq.m_iActorID);
    CHECK_NULL(0, pActorDesc);

    auto pTransferDesc = TransferDesc::Instance()->GetDesc(m_stCreateRoleReq.m_iActorID);
    CHECK_NULL(0, pTransferDesc);

    bool bFind = false;
    for (int i = 0; i < (int)pTransferDesc->transfer_id.size(); ++i)
    {
        if (pTransferDesc->transfer_id[i] == m_stCreateRoleReq.m_iExTransferID)
        {
            bFind = true;
            break;
        }
    }

    if (!bFind)
    {
        m_stCreateRoleReq.m_iExTransferID = 0;
    }

    std::string szName = m_stCreateRoleReq.m_szName.ToString();
    NFStringUtility::Trim(szName);
    std::string nameEncode = FindModule<NFIKernelModule>()->Base64Encode(szName);;

    m_ullRoleID = FindModule<NFIKernelModule>()->Get64UUID();
    proto_ff::tbName tbName;
    tbName.set_account_id(m_accountId.ToString());
    tbName.set_name(nameEncode);
    tbName.set_role_id(m_ullRoleID);
    InsertCacheDataReq<NFTransInsertName>(m_ullRoleID, 0, tbName, E_TABLE_NAME);

    SetState(EN_TCRS_INSERT_NAME);
    return 0;
}

int NFTransAccCreateRole::OnTransFinished(int iRunLogicRetCode)
{
    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_NULL(m_ullRoleID, pOnlineAcc);

    pOnlineAcc->SetAddRoleLockTime(0);

    if (iRunLogicRetCode != 0)
    {
        NotifyCreateRoleRsp(pOnlineAcc, iRunLogicRetCode);
    }
    return 0;
}

int NFTransAccCreateRole::InsertCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode, google::protobuf::Message* pMessage)
{
    int iRetCode = 0;
    if (iTableId == E_TABLE_NAME)
    {
        iRetCode = ProInsertNameRes(errCode);
        CHECK_ERR(m_ullRoleID, iRetCode, "ProInsertNameRes Failed TransInfo:{}", GetDebugInfo());
    }
    else if (iTableId == E_TABLE_ROLE_LIST)
    {
        iRetCode = ProInsertRoleListRes(errCode, pMessage);
        CHECK_ERR(m_ullRoleID, iRetCode, "ProInsertRoleListRes Failed TransInfo:{}", GetDebugInfo());
    }
    else
    {
        CHECK_ERR(m_ullRoleID, -1, "Unknown TableID:{}", iTableId);
    }
    return 0;
}

int NFTransAccCreateRole::GetCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode, google::protobuf::Message* pMessage)
{
    int iRetCode = 0;
    if (iTableId == E_TABLE_ROLE_LIST)
    {
        iRetCode = ProGetRoleListRes(errCode, pMessage);
        CHECK_ERR(m_ullRoleID, iRetCode, "ProGetRoleListRes Failed TransInfo:{}", GetDebugInfo());
    }
    return 0;
}

int NFTransAccCreateRole::SaveCacheDataRes(int ullId, int iTableId, int iReason, int32_t errCode)
{
    int iRetCode = 0;
    if (iTableId == E_TABLE_ROLE_LIST)
    {
        iRetCode = ProUpdateRoleListRes(errCode);
        CHECK_ERR(m_ullRoleID, iRetCode, "ProUpdateRoleListRes Failed TransInfo:{}", GetDebugInfo());
    }
    return 0;
}

int NFTransAccCreateRole::StartGetRoleList()
{
    proto_ff::tbRoleList tbRoleList;
    tbRoleList.set_uin(m_playerUin);
    tbRoleList.set_world_id(m_zoneId);
    tbRoleList.set_world_type(m_platformType);
    GetCacheDataSingleReq<NFTransLoadAcc>(m_ullRoleID, 0, tbRoleList, E_TABLE_ROLE_LIST);

    SetState(EN_TCRS_GET_ROLE_LIST);

    return 0;
}

int NFTransAccCreateRole::StartInsertRoleList()
{
    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_NULL_WF(m_ullRoleID, pOnlineAcc, "account is not exist!");

    proto_ff::tbRoleList tbRoleList;
    MakeNewRoleList(m_platformType, m_playerUin, reg_channel_str.ToString(), login_channel_str.ToString(), tbRoleList);

    int iRetCode = InsertCacheDataReq<NFTransInsertAcc>(m_ullRoleID, 0, tbRoleList, E_TABLE_ROLE_LIST);
    CHECK_ERR(m_ullRoleID, iRetCode, "InsertCacheDataReq NFTransInsertAcc Failed TransInfo:{}", GetDebugInfo());

    SetState(EN_TCRS_INSERT_ROLE_LIST);

    return 0;
}

int NFTransAccCreateRole::StartUpdateRoleList()
{
    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_EXPR(pOnlineAcc, -1, "account is not exist!");

    CHECK_NULL(m_playerUin, pOnlineAcc);
    RoleOne stRoleOne;
    stRoleOne.role_id = m_ullRoleID;
    stRoleOne.actor_id = m_stCreateRoleReq.m_iActorID;
    stRoleOne.name = m_stCreateRoleReq.m_szName;
    stRoleOne.actor_level = 1;
    stRoleOne.state = ROLE_STATE_CREATE;
    stRoleOne.role_ce = 0;
    stRoleOne.source_id = 0;
    stRoleOne.equip_strength_level = 0;
    stRoleOne.reg_channel_str = reg_channel_str;
    stRoleOne.login_channel_str = login_channel_str;
    stRoleOne.fashion_id.resize(proto_ff::enFashionType_MAX);
    stRoleOne.ex_transfer_id = m_stCreateRoleReq.m_iExTransferID;
    auto pTransferDesc = TransferDesc::Instance()->GetDesc(m_stCreateRoleReq.m_iActorID);
    if (pTransferDesc)
    {
        stRoleOne.transfer_id = pTransferDesc->init_transfer_id;
    }

    int iRetCode = pOnlineAcc->AddRole(stRoleOne);
    CHECK_RET(iRetCode, "pPlayerAccount->AddRole Failed!");

    proto_ff::tbRoleList tbRoleList;
    pOnlineAcc->GetData().ToPb(&tbRoleList);
    iRetCode = SaveCacheDataReq<NFTransSaveAcc>(m_playerUin, 0, tbRoleList, pOnlineAcc, E_TABLE_ROLE_LIST);
    CHECK_ERR(m_playerUin, iRetCode, "SaveCacheDataReq NFTransSaveAcc Failed TransInfo:{}", GetDebugInfo());

    SetState(EN_TCRS_UPDATE_ROLE_LIST);

    return 0;
}

int NFTransAccCreateRole::MakeNewRoleList(int iWorldType, uint64_t ullUin, const std::string& source_id, const std::string& login_source, proto_ff::tbRoleList& tbRoleList)
{
    tbRoleList.set_uin(ullUin);
    tbRoleList.set_world_id(m_zoneId);
    tbRoleList.set_world_type(iWorldType);
    tbRoleList.set_guard_start_time(0);
    tbRoleList.set_guard_end_time(0);
    tbRoleList.set_guard_msg("");

    tbRoleList.mutable_storage_data()->set_max_grids(ConstantDescEx::Instance()->GetValue(proto_ff::EN_CONST_STORAGE_PAG_NUM_OF_BRON));
    tbRoleList.mutable_storage_data()->set_buy_grids_times(0);

    proto_ff::RoleData* pRoleData = tbRoleList.mutable_role_data();
    CHECK_NULL(0, pRoleData);

    std::string szName = m_stCreateRoleReq.m_szName.ToString();
    NFStringUtility::Trim(szName);

    proto_ff::RoleOne* pRoleOne = pRoleData->add_role_list();
    CHECK_NULL(0, pRoleOne);

    LOGSVR_TRACE("Uin:" << ullUin << " Gen RoleID:" << ullUin);

    pRoleData->mutable_safe_score_data()->set_score(320);
    pRoleData->mutable_role_ext_info()->set_first_reg_time(NF_ADJUST_TIMENOW());
    pRoleOne->set_role_id(m_ullRoleID);
    pRoleOne->set_actor_id(m_stCreateRoleReq.m_iActorID);
    pRoleOne->set_actor_level(1);
    pRoleOne->set_name(szName);
    pRoleOne->set_state(proto_ff::ROLE_STATE_CREATE);
    pRoleOne->set_role_ce(0);
    pRoleOne->set_source_id(0);
    pRoleOne->clear_fashion_id();
    pRoleOne->set_reg_channel_str(source_id);
    pRoleOne->set_login_channel_str(login_source);

    auto pTransferDesc = TransferDesc::Instance()->GetDesc(m_stCreateRoleReq.m_iActorID);
    if (pTransferDesc)
    {
        pRoleOne->set_transfer_id(pTransferDesc->init_transfer_id);
    }

    for (int i = 0; i < proto_ff::enFashionType_MAX; ++i)
    {
        pRoleOne->add_fashion_id(0);
    }
    pRoleOne->set_ex_transfer_id(m_stCreateRoleReq.m_iExTransferID);

    for (int i = 0; i < (int)m_stCreateRoleReq.m_aullFriendUin.size(); ++i)
    {
        pRoleData->add_sns_friend_uin(m_stCreateRoleReq.m_aullFriendUin[i]);
    }

    pRoleData->set_regist_time(NF_ADJUST_TIMENOW());

    return 0;
}

int NFTransAccCreateRole::InitData(const proto_ff::Proto_Zone2OnLineCreateRoleReq& oCreateRoleReq)
{
    m_stCreateRoleReq.m_iActorID = oCreateRoleReq.create_role_req().actor_id();
    m_stCreateRoleReq.m_szName = oCreateRoleReq.create_role_req().name();
    m_stCreateRoleReq.m_iExTransferID = oCreateRoleReq.create_role_req().ex_transfer_id();
    m_stCreateRoleReq.m_cSecReportStr = oCreateRoleReq.create_role_req().sec_report_str()[0];
    reg_channel_str = oCreateRoleReq.reg_channel();
    login_channel_str = oCreateRoleReq.login_channel();
    m_accountId = oCreateRoleReq.account_id();

    return 0;
}

int NFTransAccCreateRole::ProInsertNameRes(int err_code)
{
    CHECK_EXPR(err_code == 0, proto_ff::ERR_CODE_ROLE_NAME_REPEATED, "name insert failed!");

    CHECK_EXPR(GetState() == EN_TCRS_INSERT_NAME, proto_ff::ERR_CODE_SYSTEM_DATABASE_ERROR, "invalid tran state!");

    int iRetCode = 0;
    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_NULL_WF(m_ullRoleID, pOnlineAcc, "account is not exist! TransInfo:{}", GetDebugInfo());

    iRetCode = StartGetRoleList();
    CHECK_ERR(m_ullRoleID, iRetCode, "StartGetRoleList failed!");

    return 0;
}

int NFTransAccCreateRole::ProInsertRoleListRes(int err_code, google::protobuf::Message* pMessage)
{
    CHECK_EXPR(err_code == 0, proto_ff::ERR_CODE_SYSTEM_OBJSTATUS_INVALID, "name insert failed!");

    CHECK_EXPR(GetState() == EN_TCRS_INSERT_ROLE_LIST, proto_ff::ERR_CODE_SYSTEM_OBJSTATUS_INVALID, "invalid tran state!");

    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_EXPR(pOnlineAcc, -1, "account is not exist!");

    auto pRoleList = dynamic_cast<proto_ff::tbRoleList*>(pMessage);
    CHECK_NULL(m_ullRoleID, pRoleList);

    pOnlineAcc->InitData(pRoleList);
    pOnlineAcc->SetInitRoleList();

    NotifyCreateRoleRsp(pOnlineAcc, 0);

    SetFinished(0);

    return 0;
}

int NFTransAccCreateRole::ProGetRoleListRes(int err_code, google::protobuf::Message* pMessage)
{
    CHECK_EXPR(GetState() == EN_TCRS_GET_ROLE_LIST, -1, "TransInfo:{}", GetDebugInfo());

    int iRetCode = 0;
    if (ERR_CODE_STORESVR_ERRCODE_SELECT_EMPTY == err_code)
    {
        iRetCode = StartInsertRoleList();
        CHECK_ERR(m_ullRoleID, iRetCode, "StartInsertRoleList failed!");
    }
    else if (err_code != 0)
    {
        LOG_ERR(m_ullRoleID, -1, "err_code: {}, TransInfo:{}", err_code, GetDebugInfo());
        return err_code;
    }
    else
    {
        iRetCode = StartUpdateRoleList();
        CHECK_ERR(m_ullRoleID, iRetCode, "StartUpdateRoleList failed!");
    }

    return 0;
}

int NFTransAccCreateRole::ProUpdateRoleListRes(int err_code)
{
    CHECK_EXPR(GetState() == EN_TCRS_UPDATE_ROLE_LIST, proto_ff::ERR_CODE_SYSTEM_OBJSTATUS_INVALID, "invalid tran state!");

    CHECK_ERR(m_playerUin, err_code, "ProUpdateRoleListRes Failed! TransInfo:{}", GetDebugInfo());

    auto pOnlineAcc = NFOnlineAccMgr::Instance()->FindOnlineAcc(m_zoneId, m_playerUin);
    CHECK_NULL(m_ullRoleID, pOnlineAcc);

    NotifyCreateRoleRsp(pOnlineAcc, 0);

    SetFinished(0);

    return 0;
}

int NFTransAccCreateRole::NotifyCreateRoleRsp(NFOnlineAcc* pAcc, int iResult)
{
    CHECK_NULL(m_playerUin, pAcc);
    tbRoleList* pRoleList = &(pAcc->GetData());

    proto_ff::Proto_OnLine2ZoneCreateRoleRes res;
    res.set_zone_id(m_zoneId);
    res.set_player_uin(m_playerUin);
    res.set_result(iResult);
    if (iResult == 0)
    {
        for (auto iter = pRoleList->role_data.role_list.list_begin(); iter != pRoleList->role_data.role_list.list_end(); ++iter)
        {
            proto_ff::RoleOne* pRoleOne = res.add_role_list();
            CHECK_NULL(0, pRoleOne);

            iter->second.ToPb(pRoleOne);
        }
    }

    FindModule<NFIServerMessageModule>()->SendTransToLogicServer(NF_ST_ONLINE_SERVER, m_fromBusId, E_ONLINE2ZONE_CREATEROLE_RES, res, m_playerUin, GetGlobalId(), m_transId);
    return 0;
}

std::string NFTransAccCreateRole::GetDebugInfo() const
{
    std::string log = NF_FORMAT("ThisGlobalID:{} CurState:{} StartTime:{} RunedTimes:{} zoneId:{} uin:{}", GetGlobalId(), m_wCurState, NFTimeUtility::DateTimeToStr(m_dwStartTime), m_wRunedTimes, m_zoneId, m_playerUin);
    return log;
}
